home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / GLUT-3.7 / PROGS / DEMOS / SKYFLY / PERFDRAW.C < prev    next >
Encoding:
C/C++ Source or Header  |  1998-08-12  |  9.0 KB  |  332 lines

  1.  
  2. /*
  3.  * perfdraw.c - $Revision: 1.4 $
  4.  */
  5.  
  6. #include <GL/glut.h>
  7. #include <math.h>
  8. #include <stdio.h>
  9. #include "skyfly.h"
  10.  
  11. #if !defined(GL_VERSION_1_1)
  12. #if defined(GL_EXT_texture_object)
  13. #define glBindTexture(A,B)     glBindTextureEXT(A,B)
  14. #define glGenTextures(A,B)     glGenTexturesEXT(A,B)
  15. #define glDeleteTextures(A,B)  glDeleteTexturesEXT(A,B)
  16. #else
  17. #define glBindTexture(A,B)
  18. #define glGenTextures(A,B)
  19. #define glDeleteTextures(A,B)
  20. #endif
  21. #endif
  22.  
  23. /* static routine decls */
  24.  
  25. extern int clouds;
  26. static void drawlitmesh_11(float *objdata);
  27. static void drawcolrtexmesh_10(float *objdata);
  28. static void drawclouds(float *objdata);
  29.  
  30. void drawperfobj(perfobj_t *perfobj)
  31. {
  32.     float     *vdata_ptr =(float *) perfobj->vdata;
  33.     extern void texenv(int), lightpos(void);
  34.  
  35.     unsigned int *flagsptr = perfobj->flags;
  36.     float     *dp;
  37.  
  38.     for (;;) {
  39.         switch (*flagsptr) {
  40.         /*
  41.          * A paper plane is a single tmesh folded on itself so the orientations
  42.          * of some triangles in the mesh are incorrect with respect to
  43.          * their normals. This is solved by drawing the tmesh twice;
  44.          * first draw only backfaces, then only frontfaces.
  45.          */
  46.         case PD_DRAW_PAPER_PLANE:
  47.             flagsptr += 1;
  48.             glCullFace(GL_FRONT);
  49.             drawlitmesh_11(vdata_ptr);
  50.             glCullFace(GL_BACK);
  51.             drawlitmesh_11((float *)((perfobj_vert_t *) vdata_ptr + 11));
  52.             glPopMatrix();
  53.             break;
  54.  
  55.         case PD_DRAW_TERRAIN_CELL:
  56.             dp = *(float **) (flagsptr + 1);
  57.             flagsptr += 2;
  58.             drawcolrtexmesh_10(dp);
  59.             break;
  60.  
  61.         case PD_DRAW_CLOUDS:
  62.                         if (rgbmode) {
  63. #if 0
  64.                             glColor3ub(0x30, 0x40, 0xb0);
  65. #else
  66.                             glColor3f(1.0f, 1.0f, 1.0f);
  67. #endif
  68.                         }
  69.             glDisable(GL_CULL_FACE);
  70.             glDisable(GL_DEPTH_TEST);
  71.             /*texenv(2);*/
  72.             drawclouds(vdata_ptr);
  73.             glEnable(GL_DEPTH_TEST);
  74.             glEnable(GL_CULL_FACE);
  75.             flagsptr += 1;
  76.             break;
  77.  
  78.         case PD_PAPER_PLANE_MODE:
  79.             switch (*(flagsptr + 1)) {
  80.             case PLANES_START:
  81.                             glShadeModel(GL_FLAT);
  82.                             glEnable(GL_LIGHTING);
  83.                             glDisable(GL_TEXTURE_2D);
  84.                             if (fog && !rgbmode)
  85.                                 glDisable(GL_FOG);
  86.                             break;
  87.             case PLANES_END:
  88.                             glShadeModel(GL_SMOOTH);
  89.                             glDisable(GL_LIGHTING);
  90.                             if (fog && !rgbmode && FOG_LEVELS > 1)
  91.                                 glEnable(GL_FOG);
  92.                             break;
  93.                         }    
  94.             flagsptr += 2;
  95.             break;
  96.  
  97.         case PD_PAPER_PLANE_POS:        /* contains the pushmatrix */
  98.             glPushMatrix();
  99.             glTranslatef(*(vdata_ptr), *(vdata_ptr + 1), *(vdata_ptr + 2));
  100.             glRotatef(*(vdata_ptr + 3), 0.0, 0.0, 1.0);
  101.             glRotatef(*(vdata_ptr + 4), 0.0, 1.0, 0.0);
  102.             glRotatef(*(vdata_ptr + 5), 1.0, 0.0, 0.0);
  103.             flagsptr += 1;
  104.             break;
  105.  
  106.         case PD_VIEWER_POS:
  107.             glLoadIdentity();
  108.             glRotatef(-90., 1.0, 0., 0.);
  109.             glRotatef(*(vdata_ptr + 3) * RAD_TO_DEG, 0.0, 0.0, 1.0); /* yaw */
  110.             lightpos();
  111.             glTranslatef(-*(vdata_ptr), -*(vdata_ptr + 1), -*(vdata_ptr + 2));
  112.             flagsptr += 1;
  113.             break;
  114.  
  115.         case PD_TEXTURE_BIND:
  116.             glBindTexture(GL_TEXTURE_2D, *(flagsptr + 1));
  117.             texenv(*(flagsptr + 1));
  118.             glEnable(GL_TEXTURE_2D);
  119.             flagsptr += 2;
  120.             break;
  121.  
  122.         case PD_END:
  123.             return;
  124.  
  125.         default:
  126.             fprintf(stderr, "Bad PD primitive %d\n", *flagsptr);
  127.             flagsptr++;
  128.             break;
  129.         }
  130.     }
  131. }
  132.  
  133. /*
  134.  * Notice how the following routines unwind loops and pre-compute indexes
  135.  * at compile time. This is crucial in obtaining the maximum data transfer 
  136.  * from cpu to the graphics pipe.
  137.  */
  138. static void drawlitmesh_11(float *op)
  139. {
  140.     glBegin(GL_TRIANGLE_STRIP);
  141.     /* one */
  142.     glNormal3fv((op + PD_V_NORMAL));
  143.     glVertex3fv((op + PD_V_POINT));
  144.     /* two */
  145.     glNormal3fv((op + (PD_V_SIZE + PD_V_NORMAL)));
  146.     glVertex3fv((op + (PD_V_SIZE + PD_V_POINT)));
  147.     /* three */
  148.     glNormal3fv((op + (2 * PD_V_SIZE + PD_V_NORMAL)));
  149.     glVertex3fv((op + (2 * PD_V_SIZE + PD_V_POINT)));
  150.     /* four */
  151.     glNormal3fv((op + (3 * PD_V_SIZE + PD_V_NORMAL)));
  152.     glVertex3fv((op + (3 * PD_V_SIZE + PD_V_POINT)));
  153.     /* five */
  154.     glNormal3fv((op + (4 * PD_V_SIZE + PD_V_NORMAL)));
  155.     glVertex3fv((op + (4 * PD_V_SIZE + PD_V_POINT)));
  156.     /* six */
  157.     glNormal3fv((op + (5 * PD_V_SIZE + PD_V_NORMAL)));
  158.     glVertex3fv((op + (5 * PD_V_SIZE + PD_V_POINT)));
  159.     /* seven */
  160.     glNormal3fv((op + (6 * PD_V_SIZE + PD_V_NORMAL)));
  161.     glVertex3fv((op + (6 * PD_V_SIZE + PD_V_POINT)));
  162.     /* eight */
  163.     glNormal3fv((op + (7 * PD_V_SIZE + PD_V_NORMAL)));
  164.     glVertex3fv((op + (7 * PD_V_SIZE + PD_V_POINT)));
  165.     /* nine */
  166.     glNormal3fv((op + (8 * PD_V_SIZE + PD_V_NORMAL)));
  167.     glVertex3fv((op + (8 * PD_V_SIZE + PD_V_POINT)));
  168.     /* ten */
  169.     glNormal3fv((op + (9 * PD_V_SIZE + PD_V_NORMAL)));
  170.     glVertex3fv((op + (9 * PD_V_SIZE + PD_V_POINT)));
  171.     /* eleven */
  172.     glNormal3fv((op + (10 * PD_V_SIZE + PD_V_NORMAL)));
  173.     glVertex3fv((op + (10 * PD_V_SIZE + PD_V_POINT)));
  174.  
  175.     glEnd();
  176.  
  177. }
  178.  
  179. static void drawcolrtexmesh_10(float *op)
  180. {
  181.     glBegin(GL_TRIANGLE_STRIP);
  182.     /* one */
  183.     glTexCoord2fv((op + PD_V_TEX));
  184.     glColor3fv((op + PD_V_COLOR));
  185.     glVertex3fv((op + PD_V_POINT));
  186.     /* two */
  187.     glTexCoord2fv((op + (PD_V_SIZE + PD_V_TEX)));
  188.     glColor3fv((op + (PD_V_SIZE + PD_V_COLOR)));
  189.     glVertex3fv((op + (PD_V_SIZE + PD_V_POINT)));
  190.     /* three */
  191.     glTexCoord2fv((op + (2 * PD_V_SIZE + PD_V_TEX)));
  192.     glColor3fv((op + (2 * PD_V_SIZE + PD_V_COLOR)));
  193.     glVertex3fv((op + (2 * PD_V_SIZE + PD_V_POINT)));
  194.     /* four */
  195.     glTexCoord2fv((op + (3 * PD_V_SIZE + PD_V_TEX)));
  196.     glColor3fv((op + (3 * PD_V_SIZE + PD_V_COLOR)));
  197.     glVertex3fv((op + (3 * PD_V_SIZE + PD_V_POINT)));
  198.     /* five */
  199.     glTexCoord2fv((op + (4 * PD_V_SIZE + PD_V_TEX)));
  200.     glColor3fv((op + (4 * PD_V_SIZE + PD_V_COLOR)));
  201.     glVertex3fv((op + (4 * PD_V_SIZE + PD_V_POINT)));
  202.     /* six */
  203.     glTexCoord2fv((op + (5 * PD_V_SIZE + PD_V_TEX)));
  204.     glColor3fv((op + (5 * PD_V_SIZE + PD_V_COLOR)));
  205.     glVertex3fv((op + (5 * PD_V_SIZE + PD_V_POINT)));
  206.     /* seven */
  207.     glTexCoord2fv((op + (6 * PD_V_SIZE + PD_V_TEX)));
  208.     glColor3fv((op + (6 * PD_V_SIZE + PD_V_COLOR)));
  209.     glVertex3fv((op + (6 * PD_V_SIZE + PD_V_POINT)));
  210.     /* eight */
  211.     glTexCoord2fv((op + (7 * PD_V_SIZE + PD_V_TEX)));
  212.     glColor3fv((op + (7 * PD_V_SIZE + PD_V_COLOR)));
  213.     glVertex3fv((op + (7 * PD_V_SIZE + PD_V_POINT)));
  214.     /* nine */
  215.     glTexCoord2fv((op + (8 * PD_V_SIZE + PD_V_TEX)));
  216.     glColor3fv((op + (8 * PD_V_SIZE + PD_V_COLOR)));
  217.     glVertex3fv((op + (8 * PD_V_SIZE + PD_V_POINT)));
  218.     /* ten */
  219.     glTexCoord2fv((op + (9 * PD_V_SIZE + PD_V_TEX)));
  220.     glColor3fv((op + (9 * PD_V_SIZE + PD_V_COLOR)));
  221.     glVertex3fv((op + (9 * PD_V_SIZE + PD_V_POINT)));
  222.  
  223.     glEnd();
  224. }
  225.  
  226. static void drawclouds(float *op)
  227. {
  228. #define SKY_STRIPS 24
  229.  
  230.     /* Break into quad strips so cheap fog works better */
  231.     if (0 == clouds) {
  232.  
  233.         GLfloat *vc0, *vc1, *vc2;
  234.         GLfloat *tc0, *tc1, *tc2;
  235.         GLfloat sky_s0, sky_s1, sky_t0, sky_t1;
  236.         GLfloat sky_x0, sky_x1, sky_y0, sky_y1, sky_z;
  237.         int ii, jj;
  238.         GLfloat s0, s1, t0, t1;
  239.         GLfloat x0, x1, y0, y1, z0;
  240.  
  241.         vc0 = op + PD_V_POINT;
  242.         vc1 = op + PD_V_POINT + PD_V_SIZE;
  243.         vc2 = op + PD_V_POINT + PD_V_SIZE * 2;
  244.  
  245.         tc0 = op + PD_V_TEX;
  246.         tc1 = op + PD_V_TEX + PD_V_SIZE;
  247.         tc2 = op + PD_V_TEX + PD_V_SIZE * 2;
  248.  
  249.         sky_s0 = tc0[0];
  250.         sky_s1 = tc1[0];
  251.         sky_t0 = tc0[1];
  252.         sky_t1 = tc2[1];
  253.  
  254.         sky_x0 = vc0[0];
  255.         sky_x1 = vc1[0];
  256.         sky_y0 = vc0[1];
  257.         sky_y1 = vc2[1];
  258.         sky_z  = vc0[2];
  259.  
  260.         clouds = glGenLists(1);
  261.  
  262.         glNewList(clouds, GL_COMPILE);
  263.  
  264.         s1 = (1.0f / SKY_STRIPS) * (sky_s1 - sky_s0);
  265.         t1 = (1.0f / SKY_STRIPS) * (sky_t1 - sky_t0);
  266.         x1 = (1.0f / SKY_STRIPS) * (sky_x1 - sky_x0);
  267.         y1 = (1.0f / SKY_STRIPS) * (sky_y1 - sky_y0);
  268.  
  269.         z0 = sky_z;
  270.         s0 = sky_s0;
  271.         x0 = sky_x0;
  272.  
  273.         for (ii = 0; ii < SKY_STRIPS; ii++, s0 += s1, x0 += x1) {
  274.  
  275.             t0 = sky_t0;
  276.             y0 = sky_y0;
  277.  
  278.             glBegin(GL_QUAD_STRIP);
  279.  
  280.             glTexCoord2f(s0, t0);
  281.             glVertex3f(x0, y0, z0);
  282.  
  283.             glTexCoord2f(s0 + s1, t0);
  284.             glVertex3f(x0 + x1, y0, z0);
  285.  
  286.             for (jj = 0; jj < SKY_STRIPS; jj++, t0 += t1, y0 += y1) {
  287.  
  288.                 glTexCoord2f(s0 + s1, t0 + t1);
  289.                 glVertex3f(x0 + x1, y0 + y1, z0);
  290.  
  291.                 glTexCoord2f(s0, t0 + t1);
  292.                 glVertex3f(x0, y0 + y1, z0);
  293.             }
  294.  
  295.             glEnd();
  296.  
  297.         }
  298.  
  299.         glEndList();
  300.     }
  301.  
  302.     glCallList(clouds);
  303. }
  304.  
  305. void putv3fdata(float *v, perfobj_vert_t *ptr)
  306. {
  307.   ptr->vert[0] = v[0];
  308.   ptr->vert[1] = v[1];
  309.   ptr->vert[2] = v[2];
  310. }
  311.  
  312. void putc3fdata(float *c, perfobj_vert_t *ptr)
  313. {
  314.   ptr->color[0] = c[0];
  315.   ptr->color[1] = c[1];
  316.   ptr->color[2] = c[2];
  317. }
  318.  
  319. void putn3fdata(float *n, perfobj_vert_t *ptr)
  320. {
  321.   ptr->normal[0] = n[0];
  322.   ptr->normal[1] = n[1];
  323.   ptr->normal[2] = n[2];
  324. }
  325.  
  326. void putt2fdata(float *t, perfobj_vert_t *ptr)
  327. {
  328.   ptr->texture[0] = t[0];
  329.   ptr->texture[1] = t[1];
  330. }
  331.  
  332.